package com.company;
/*Java 多线程编程
Java 给多线程编程提供了内置的支持。 一条线程指的是进程中一个单一顺序的控制流，
一个进程中可以并发多个线程，每条线程并行执行不同的任务。

多线程是多任务的一种特别的形式，但多线程使用了更小的资源开销。

这里定义和线程相关的另一个术语 - 进程：一个进程包括由操作系统分配的内存空间，包含一个或多个线程。
一个线程不能独立的存在，它必须是进程的一部分。一个进程一直运行，直到所有的非守护线程都结束运行后才能结束。

多线程能满足程序员编写高效率的程序来达到充分利用 CPU 的目的*/

public class C07MultiThreadingSynchronized {

//    synchronized基本规则
//    我们将synchronized的基本规则总结为下面3条，并通过实例对它们进行说明。

//    第一条: 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时，
//    其他线程对“该对象”的该“synchronized方法”或者“synchronized代码块”的访问将被阻塞。
//run()方法中存在“synchronized(this)代码块”，而且t1和t2都是基于"demo这个Runnable对象"创建的线程。
//    这就意味着，我们可以将synchronized(this)中的this看作是“demo这个Runnable对象”；
//    因此，线程t1和t2共享“demo对象的同步锁”。所以，当一个线程运行的时候，
//    另外一个线程必须等待“运行线程”释放“demo的同步锁”之后才能运行。
//    public static void main(String[] args) {
//
//        MyRunnable myRunnable=new MyRunnable();
//        Thread mt1 = new Thread(myRunnable);
//        Thread mt2 = new Thread(myRunnable);
//        mt1.start();
//        mt2.start();
//
//    }
//
//    public static class MyRunnable implements Runnable {
//        @Override()
//        public void run() {
////            含有synchronized同步块的方法
//            synchronized (this) {
//
//                for (Integer i = 1; i <= 10; i++) {
//                    try {
//                        Thread.currentThread().sleep(1000);
//                        System.out.println(Thread.currentThread().getName()  + String.format("%02d", i));
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//
//
//                }
//            }
//        }
//    }

//    //    第二条: 当一个线程访问“某对象”的“synchronized方法”
//    //    或者“synchronized代码块”时，其他线程仍然可以访问“该对象”的非同步代码块。
//    public static void main(String[] args) {
//
//        MySynchronizedTestClass mc=new MySynchronizedTestClass();
//        Thread mt1 = new Thread(new Runnable() {
//            @Override
//            public void run() {
//                mc.synchronizedMethod();
//            }
//        });
//        Thread mt2 = new Thread(new Runnable() {
//            @Override
//            public void run() {
//                mc.nonSynchronizedMethod();
//            }
//        });
//        mt1.start();
//        mt2.start();
//    }
//
//    public static class MySynchronizedTestClass {
//        public MySynchronizedTestClass() {
//
//        }
//        // synchronized同步代码块
//        public void synchronizedMethod() {
//            synchronized (this) {
//                for (Integer i = 1; i <= 10; i++) {
//                    try {
//                        Thread.currentThread().sleep(1000);
//                        System.out.println(Thread.currentThread().getName()+"-" + String.format("%02d", i));
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                }
//
//            }
//
//        }
//        // 非同步代码块
//        public void nonSynchronizedMethod() {
//                for (Integer i = 1; i <= 10; i++) {
//                    try {
//                        Thread.currentThread().sleep(1000);
//                        System.out.println(Thread.currentThread().getName() +"-"+ String.format("%02d", i));
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                }
//
//
//        }
//
//    }
//    第三条: 当一个线程访问“某对象”的“synchronized方法”
//    或者“synchronized代码块”时，其他线程对“该对象”的其他的“synchronized方法”
//    或者“synchronized代码块”的访问将被阻塞。

//    public static void main(String[] args) throws InterruptedException {
//
//        MySynchronizedTestClass mc=new MySynchronizedTestClass();
//        Thread mt1 = new Thread(new Runnable() {
//            @Override
//            public void run() {
//                mc.synchronizedMethod1();
//            }
//        });
//        Thread mt2 = new Thread(new Runnable() {
//            @Override
//            public void run() {
//                mc.synchronizedMethod2();
//            }
//        });
//        mt1.start();
//        mt2.start();
//        mt1.join();
//        mt2.join();
//
//    }
//
//    public static class MySynchronizedTestClass {
//        public MySynchronizedTestClass() {
//
//        }
//        // synchronized同步代码块1
//        public void synchronizedMethod1() {
//            synchronized (this) {
//                for (Integer i = 1; i <= 10; i++) {
//                    try {
//                        Thread.currentThread().sleep(1000);
//                        System.out.println(Thread.currentThread().getName()+"-" + String.format("%02d", i));
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                }
//
//            }
//
//        }
//        // synchronized同步方法
//        public synchronized  void synchronizedMethod2() {
//                for (Integer i = 1; i <= 10; i++) {
//                    try {
//                        Thread.currentThread().sleep(1000);
//                        System.out.println(Thread.currentThread().getName() + "-" + String.format("%02d", i));
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                }
//
//        }
//
//    }

//    实例锁 和 全局锁
//    实例锁 -- 锁在某一个实例对象上。如果该类是单例，那么该锁也具有全局锁的概念。
//    实例锁对应的就是synchronized关键字。
//    全局锁 -- 该锁针对的是类，无论实例多少个对象，那么线程都共享该锁。
//    全局锁对应的就是static synchronized（或者是锁在该类的class或者classloader对象上）。
//
//    关于“实例锁”和“全局锁”有一个很形象的例子：
//
//    pulbic class Something {
//        public synchronized void isSyncA(){} 实例锁A(实例：必须new一个类才能调用改方法)
//        public synchronized void isSyncB(){} 实例锁B
//        public static synchronized void cSyncA(){} 全局锁A (static:静态方法，不需要new)
//        public static synchronized void cSyncB(){} 全局锁B
//    }
//    假设，Something有两个实例x和y。分析下面4组表达式获取的锁的情况。
//            (01) x.isSyncA()与x.isSyncB()
//                    同一实例x,不能同时访问实例锁A和 实例锁B
//            (02) x.isSyncA()与y.isSyncA()
//                    不同实例x，y,可以同时访问实例锁A和 实例锁B 。因为他们是不同的对象（实例x，实例y）
//            (03) x.cSyncA()与y.cSyncB()
//                    x，y=Something,不可以同时访问全局锁A和 全局锁B 。因为他们都等于=Something
//            (04) x.isSyncA()与Something.cSyncA()
//                     可以被同时访问。因为isSyncA()是实例方法，x.isSyncA()使用的是对象x的锁；而cSyncA()是静态方法，Something.cSyncA()可以理解对使用的是“类的锁”。因此，它们是可以被同时访问的。
//                      x=实例x ， Something 其实他们是不同的对象。 x=实例x ， Something 其实他们是不同的对象。
}
